package com.sailing.xjpb.common;

import com.sailing.xjpb.common.converters.*;
import org.apache.commons.lang3.ClassUtils;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Internal class for converting between wrapper types(including primitives).
 * Only intended for internal use.
 * 根据org.dozer.converters.PrimitiveOrWrapperConverter修改的
 *
 * @author tierney.matt
 * @author garsombke.franz
 * @author benson.matt
 * @author dmitry.buzdin
 */
public class DataConverter implements Serializable {

    private static final long serialVersionUID = 1L;

    private static final Map<Class<?>, Converter> CONVERTER_MAP = new HashMap<>(16);

    static {
        CONVERTER_MAP.put(Integer.class, new IntegerConverter());
        CONVERTER_MAP.put(Double.class, new DoubleConverter());
        CONVERTER_MAP.put(Short.class, new ShortConverter());
        CONVERTER_MAP.put(Character.class, new CharacterConverter());
        CONVERTER_MAP.put(Long.class, new LongConverter());
        CONVERTER_MAP.put(Boolean.class, new BooleanConverter());
        CONVERTER_MAP.put(Byte.class, new ByteConverter());
        CONVERTER_MAP.put(Float.class, new FloatConverter());
        CONVERTER_MAP.put(BigDecimal.class, new BigDecimalConverter());
        CONVERTER_MAP.put(BigInteger.class, new BigIntegerConverter());
        CONVERTER_MAP.put(Class.class, new ClassConverter());
        CONVERTER_MAP.put(List.class, new ListConverter());
    }

    public <T> T convert(Object srcFieldValue, Class<T> destFieldClass) {
        if (srcFieldValue == null || destFieldClass == null
                || (srcFieldValue.equals("") && !destFieldClass.equals(String.class))) {
            return null;
        }
        Converter converter = getConverter(destFieldClass);
        return converter.convert(destFieldClass, srcFieldValue);
    }

    private <T> Converter getConverter(Class<T> destClass) {
        if (String.class.equals(destClass)) {
            return new StringConverter();
        }

        Converter result = CONVERTER_MAP.get(ClassUtils.primitiveToWrapper(destClass));

        if (result == null) {
            if (java.util.Date.class.isAssignableFrom(destClass)) {
                result = new DateConverter();
            } else if (Calendar.class.isAssignableFrom(destClass)) {
                result = new CalendarConverter();
            }
        }
        return result == null ? new StringConverter() : result;
    }

    public boolean accepts(Class<?> aClass) {
        return aClass.isPrimitive() || Number.class.isAssignableFrom(aClass) || String.class.equals(aClass)
                || Character.class.equals(aClass) || Boolean.class.equals(aClass)
                || java.util.Date.class.isAssignableFrom(aClass) || Calendar.class.isAssignableFrom(aClass);
    }

}